package cn.zn.verify.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import cn.zn.base.bean.dto.ResultData;
import cn.zn.base.bean.vo.BaseApiVo;
import cn.zn.base.common.utils.ResultUtil;
import cn.zn.base.exception.CustomException;
import cn.zn.verify.annotation.Custom;
import cn.zn.verify.annotation.Required;
import cn.zn.verify.service.DataAcceptService;
import cn.zn.verify.strategy.impl.CustomVerifyStrategy;
import cn.zn.verify.strategy.impl.RequiredVerifyStrategy;
import cn.zn.verify.utils.VerifyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;

@Service
public abstract class DataAcceptServiceImpl<T extends BaseApiVo> implements DataAcceptService<T> {

    private static final Logger logger = LoggerFactory.getLogger(DataAcceptServiceImpl.class);

    @Override
    public ResultData acceptData(String data) {
        // json转对象
        List<T> list;
        if (JSONUtil.isJsonArray(data)) {
            list = new ArrayList<>(JSONUtil.toList(data, getTClass()));
        } else if (JSONUtil.isJsonObj(data)) {
            list = new ArrayList<>();
            list.add(JSONUtil.toBean(data, getTClass()));
        } else {
            throw new CustomException("数据格式不正确");
        }

        // 验证后的数据集
        List<T> successList = new ArrayList<>();
        List<T> errorList = new ArrayList<>();

        // 数据校验
        verify(list, successList, errorList);

        // 保存验证通过的数据，并返回保存失败的数据
        List<T> otherErrs = doAcceptData(list);
        if (CollUtil.isNotEmpty(otherErrs)) {
            errorList.addAll(otherErrs);
        }

        if (CollUtil.isNotEmpty(errorList)) {
            return ResultUtil.error("校验未通过数据", errorList);
        }

        return ResultUtil.success();
    }

    /**
     * 数据校验
     *
     * @param list        数据
     * @param successList 正确数据
     * @param errorList   错误数据
     */
    private void verify(List<T> list, List<T> successList, List<T> errorList) {
        if (CollUtil.isEmpty(list)) {
            throw new CustomException("数据为空");
        }

        for (T vo : list) {
            Class<? extends BaseApiVo> clazz = vo.getClass();
            Field[] fields = clazz.getDeclaredFields();
            List<String> errMessages = new ArrayList<>();
            for (Field field : fields) {
                Object value = getValue(field, vo);
                errMessages.addAll(verifyValue(value, vo, field.getAnnotations()));
            }

            // 错误信息不为空，则加入错误集中
            if (CollUtil.isNotEmpty(errMessages)) {
                vo.setErrMsg(StrUtil.join(";", errMessages));
                errorList.add(vo);
            } else {
                successList.add(vo);
            }
        }
    }

    /**
     * 获取值
     *
     * @param field 字段
     * @param vo    bean
     * @return 结果
     */
    private Object getValue(Field field, T vo) {
        try {
            field.setAccessible(true);
            return field.get(vo);
        } catch (Exception e) {
            logger.error("获取值错误：", e);
        }
        return null;
    }

    /**
     * 校验
     *
     * @param value       值
     * @param annotations 校验规则
     * @return 结果
     */
    private List<String> verifyValue(Object value, T vo, Annotation[] annotations) {
        List<String> errMessages = new ArrayList<>();
        if (ArrayUtil.isNotEmpty(annotations)) {
            VerifyUtil<T> verifyUtil = null;
            for (Annotation annotation : annotations) {
                if (annotation instanceof Required) {
                    verifyUtil = new VerifyUtil<>(new RequiredVerifyStrategy<>());
                } else if (annotation instanceof Custom) {
                    verifyUtil = new VerifyUtil<>(new CustomVerifyStrategy<>());
                }
                if (verifyUtil != null) {
                    String errMsg = verifyUtil.verify(value, vo, annotation);
                    if (StrUtil.isNotBlank(errMsg)) {
                        errMessages.add(errMsg);
                    }
                }
            }
        }
        return errMessages;
    }

    @SuppressWarnings("unchecked")
    private Class<T> getTClass() {
        return (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    /**
     * 保存数据
     *
     * @param list 验证通过的数据
     * @return 结果
     */
    public abstract List<T> doAcceptData(List<T> list);

}
